/*
 * $Id: AlphabetListView.java 538 2008-08-19 08:19:28Z jasta00 $
 *
 * Copyright (C) 2008 Josh Guilfoyle <jasta@devtcg.org>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

package org.devtcg.five.music.widget;

import java.util.Map;

import org.devtcg.five.music.R;

import android.content.Context;
import android.database.Cursor;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.LayoutInflater;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Custom list widget that will section a sorted list by alphabet letters and
 * create an access bar overlayed onto the list.
 */
public class AlphabetListView extends RelativeLayout
{
	private static final String TAG = "AlphabetListView";

	protected ListView mList;
	protected AlphabetSectionedAdapter mAdapter;
	protected AlphabetBar mAlphabetBar;
	
	public AlphabetListView(Context ctx)
	{
		super(ctx);
		init();
	}

	public AlphabetListView(Context ctx, AttributeSet attrs)
	{
		super(ctx, attrs);
		init();
	}

	private void init()
	{
		LayoutInflater inf = LayoutInflater.from(mContext);

		View root = inf.inflate(R.layout.alphabet_list, this);

		mList = (ListView)root.findViewById(android.R.id.list);
		mList.setVerticalScrollBarEnabled(false);

		mAlphabetBar = (AlphabetBar)root.findViewById(R.id.alphabet_bar);
		mAlphabetBar.setLabelClickListener(mBarLabelClicked);
	}

	/**
	 * Set the underlying ListView adapter properties.  You must not directly
	 * set your own ListAdapter else the alphabet bar will cease to function.
	 *  
	 * @param layout_row
	 *   Layout resource ID for the main list rows.
	 *   
	 * @param layout_sep
	 *   Layout resource ID for the alphabet separator.
	 *  
	 * @param c
	 *   Database cursor to feed this adapter.  Eventually I'd like to support
	 *   other data sources, but that is not in the cards right now.
	 * 
	 * @param from
	 *   Same as the parameters for SimpleCursorAdapter.  Together with
	 *   <code>to</code>, defines a mapping of database columns to layout
	 *   views.
	 *   
	 * @param to
	 *   Same as the parameters for SimpleCursorAdapter.
	 * 
	 * @param sig_col
	 *   Column position (see {@link android.database.Cursor#getColumnIndex(String)})
	 *   of the sorted field.  That is, the field from which to generate the
	 *   alphabet labels.
	 * 
	 * @see android.widget.SimpleCursorAdapter
	 */
	public void setAdapterParameters(int layout_row, int layout_sep, Cursor c,
	  String[] from, int[] to, int sig_col)
	{
		mAdapter = new AlphabetSectionedAdapter(mContext,
		  layout_row, layout_sep, c, from, to, sig_col);

		mList.setAdapter(mAdapter);
	}

	/**
	 * Access the underlying list view directly.  Necessary to respond to item
	 * clicks and perhaps do other interesting things I did not imagine.
	 */
	public ListView getListView()
	{
		return mList;  
	}
	
	/**
	 * Access the underlying AlphabetSectionedAdapter.  Valid only after a call
	 * to {@link #setAdapterParameters}.
	 */
	public AlphabetSectionedAdapter getAdapter()
	{
		return mAdapter;
	}
	
	/**
	 * Access the underlying alphabet bar directly.  Not useful at present,
	 * perhaps some day the alphabet bar will have properties or methods that
	 * will be useful.
	 */
	public AlphabetBar getAlphabetBar()
	{
		return mAlphabetBar;
	}

	private OnClickListener mBarLabelClicked = new OnClickListener()
	{
		public void onClick(View v)
		{
			char label = ((TextView)v).getText().charAt(0);

			int pos = mAdapter.getLabelPosition(label);

			String text = "Clicked label '" + label + "', position=" + pos;
			Log.d(TAG, text);
			
			if (pos == -1)
			{
				Log.d(TAG, "No exact match for '" + label + "', spreading search...");
				
				if ((pos = findNearestPosition(label)) == -1)
				{
					Log.d(TAG, "List is empty?");
					return;
				}
			}

			mList.setSelectionFromTop(pos, 0);
		}

		public int findNearestPosition(char label)
		{
			int pos;
			char up = label;
			char down = label;
			
			assert label == '#' || (label >= 'A' && label <= 'Z');
			
			while (up >= 'A' || down <= 'Z')
			{
				if (down <= 'Z')
				{
					if ((pos = mAdapter.getLabelPosition(down++)) >= 0)
						return pos;
				}

				if (up >= 'A')
				{
					if ((pos = mAdapter.getLabelPosition(up--)) >= 0)
						return pos;
				}
			}

			return -1;
		}
	};
}
